package com.auxgroup.hr.front.site.co;

import com.auxgroup.hr.front.commons.BaseRetCode;
import com.auxgroup.hr.front.commons.enums.WfActionTypeEnum;
import com.auxgroup.hr.front.commons.enums.WfStatusEnum;
import com.auxgroup.hr.front.commons.enums.WfTypeEnum;
import com.auxgroup.hr.front.commons.vo.AuthorityFiledVO;
import com.auxgroup.hr.front.commons.vo.BaseResponseVO;
import com.auxgroup.hr.front.commons.vo.UserDTO;
import com.auxgroup.hr.front.dao.domain.*;
import com.auxgroup.hr.front.dao.repository.PsCJobCurrVwRepository;
import com.auxgroup.hr.front.service.process.ModAttTService;
import com.auxgroup.hr.front.service.process.ProcessService;
import com.auxgroup.hr.front.site.co.process.WfDrftHdrCO;
import com.auxgroup.hr.front.site.inteceptor.SessionGain;
import com.auxgroup.hr.front.site.vo.BaseProcessRespVO;
import com.auxgroup.hr.front.site.vo.process.BaseApproveReq;
import com.auxgroup.hr.front.site.vo.process.BaseWsRespVO;
import com.auxgroup.hr.front.site.vo.process.WfPrcHdrSaveQueVO;
import com.auxgroup.hr.front.ws.ProcessApplyQueDTO;
import com.auxgroup.hr.front.ws.ProcessApproveQueDTO;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.beanutils.converters.BigDecimalConverter;
import org.apache.commons.beanutils.converters.DateConverter;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;

import javax.validation.Valid;
import java.lang.reflect.InvocationTargetException;
import java.math.BigDecimal;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * Created by nitongqian on 2019/1/23.
 */
public abstract class BaseWfCO extends BaseCO {
    protected abstract Set<String> getAuthFileds();

    @Autowired
    protected ProcessService processService;
    @Autowired
    protected ModAttTService modAttTService;
    @Autowired
    protected PsCJobCurrVwRepository psCJobCurrVwRepository;


    //填充流程基础字段
    protected void fillBaseWfInfo(UserDTO user, AbsWfDomain wfXfrHdr, BaseProcessRespVO respVo) {
        //设置附件数据
        respVo.setWfFiles(modAttTService.getWfFiles(wfXfrHdr.getcTransactionNbr(), user));
        //设置权限字段
        if(getAuthFileds() != null) {
            respVo.setAuthFileds(processService.buildAuthFieldVo(wfXfrHdr, user, wfXfrHdr.getcTransactionNbr(), getAuthFileds()));
        }
        //设置按钮权限
        respVo.fillStepInfo(processService.getStepInst(wfXfrHdr.getcTransactionNbr(), user));
    }


    //填充流程基础字段
    protected void fillBaseWfInfo(UserDTO user, AbsWfDomain wfXfrHdr, String stepNumber, BaseProcessRespVO respVo) {
        //设置附件数据
        respVo.setWfFiles(modAttTService.getWfFiles(wfXfrHdr.getcTransactionNbr(), user));
        //设置权限字段
        if(getAuthFileds() != null) {
            respVo.setAuthFileds(processService.buildAuthFieldVo(wfXfrHdr, stepNumber, wfXfrHdr.getcTransactionNbr(), getAuthFileds()));
        }
        //设置按钮权限
        respVo.fillStepInfo(processService.getStepInst(wfXfrHdr.getcTransactionNbr(), user));
        if(!respVo.hasFieldEdit() && respVo.getAuthFileds() != null) {
            respVo.getAuthFileds().forEach(a -> {
                a.setIsEdit(false);
            });
        }


    }
    protected static final Logger logger = LoggerFactory.getLogger(BaseWfCO.class);

    protected Set<String> getEditableFields(AbsWfDomain orignObj, UserDTO user) {
        Set<AuthorityFiledVO> auths = processService.buildAuthFieldVo(orignObj, user,
                orignObj.getcTransactionNbr(), getAuthFileds());
        return auths.stream().filter(a -> a.getIsEdit())
                .map(x -> x.getFieldKey()).collect(Collectors.toSet());
    }
    //填充修改的字段
    protected void fillParams(AbsWfDomain orignObj, UserDTO user, Object request) {
        Set<AuthorityFiledVO> auths = processService.buildAuthFieldVo(orignObj, user,
                orignObj.getcTransactionNbr(), getAuthFileds());
//BeanUtils.get
        ConvertUtils.register(new DateConverter(null), java.util.Date.class);
        ConvertUtils.register(new BigDecimalConverter(null), BigDecimal.class);
        for(AuthorityFiledVO auth : auths) {
            if(auth.getIsEdit()) {
                try {
                    BeanUtils.copyProperty(orignObj, auth.getFieldKey(), request);
                    BeanUtils.setProperty(orignObj, auth.getFieldKey(),
                            BeanUtils.getProperty(request, auth.getFieldKey()));
                } catch (Exception e) {
                    e.printStackTrace();
                    logger.error("属性设置错误", e);
                }
            }
        }
    }


    //通用的提交到ps系统并处理返回结果
    protected BaseResponseVO requestWs(String wfType, BaseApproveReq requestVO, UserDTO user) {
        ProcessApproveQueDTO requestDTO = requestVO.init(user.getOprId(),
                wfType);
        Map<String, String> approveResult = processService.approve(requestDTO);
        if(approveResult==null||approveResult.isEmpty()){
            return buildRespone(BaseRetCode.CODE_ERROR_PROCESS_APRROVE_FAIL);
        }
        if("0".equals(approveResult.get("C_MSG_CODE"))){
            return buildRespone(BaseRetCode.CODE_SUCCESS,"提交成功");
        }else{
            return buildRespone(approveResult.get("C_MSG_CODE"), approveResult.get("C_MSG_TEXT"));
        }
    }

    //提交流程前填充信息
    protected boolean fillBeforeSubmit(@RequestBody AbsWfEmplDomain laveReq, UserDTO user) {
        String cTransactionNbr = laveReq.getcTransactionNbr();

        if(StringUtils.isBlank(cTransactionNbr)){
            cTransactionNbr = processService.getTranNum();
            if(StringUtils.isBlank(cTransactionNbr)){
                return false;
            }
        }
        laveReq.setcTransactionNbr(cTransactionNbr);

        return true;
    }
    /**
     * submit发起流程
     * @param user
     * @param wkotHdr
     * @return
     */
    protected BaseResponseVO submitWf(UserDTO user, String wfType, AbsWfEmplDomain wkotHdr) {
        ProcessApplyQueDTO requestDTO = new ProcessApplyQueDTO();
        if(WfStatusEnum.WF_STATUS_S.getStatus().equals(wkotHdr.getcWfStatus())){
            requestDTO.setC_ACTION_TYPE(WfActionTypeEnum.WF_ACTION_SUBMIT.getAction());
        }else{
            requestDTO.setC_ACTION_TYPE(WfActionTypeEnum.WF_ACTION_RESUBMIT.getAction());
        }
        requestDTO.setC_TRANSACTION_NBR(wkotHdr.getcTransactionNbr());
        requestDTO.setC_USERID(user.getOprId());
        requestDTO.setC_WF_TYPE(wfType);
        Map<String, String> approveResult = processService.apply(requestDTO);
        if(approveResult==null||approveResult.isEmpty()){
            return buildRespone(BaseRetCode.CODE_ERROR_PROCESS_APPLY_FAIL);
        }
        if("0".equals(approveResult.get("C_MSG_CODE"))){
            return buildRespone(wkotHdr.getcTransactionNbr());
        }else{
            //只有初次发起时，发起失败才删除数据
            return buildRespone(approveResult.get("C_MSG_CODE"), approveResult.get("C_MSG_TEXT"));
        }
    }
}
